package com.shchuangzhi.smartguard.core;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.ClientException;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.ServiceException;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSStsTokenCredentialProvider;
import com.alibaba.sdk.android.oss.model.PutObjectRequest;
import com.alibaba.sdk.android.oss.model.PutObjectResult;
import com.elvishew.xlog.XLog;
import com.facebook.stetho.server.http.HttpStatus;
import com.shchuangzhi.smartguard.SharedPref;
import com.shchuangzhi.smartguard.core.command.Command;
import com.shchuangzhi.smartguard.core.command.ImageCredentialDownloadCommand;
import com.shchuangzhi.smartguard.core.command.ImageUpdateCommand;
import com.shchuangzhi.smartguard.core.receiver.ReceiverInOutData;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by j_hu on 11/20/17.
 */

public class ImageUploader extends AsyncTask<ImageUploader.AsyncTaskType, Void, ImageUploader.ExecuteResult> {
    private static Context context;
    private static File mediaFile;
    private static ReceiverInOutData.InOutDataView bindData;
    private static ImageCredentialDownloadCommand.OSSResult ossResult;
    private static final int MEDIA_TYPE_IMAGE = 1;

    public static ImageUploader getInstance() {
        return new ImageUploader();
    }

    public void init(Context ctx) {
        context = ctx;
    }

    public void bindData(ReceiverInOutData.InOutDataView data) {
        bindData = data;
    }

    @Override
    protected ExecuteResult doInBackground(AsyncTaskType... params) {
        ExecuteResult result = null;
        if (params[0] == AsyncTaskType.GET_TOKEN) {
            ImageCredentialDownloadCommand command = new ImageCredentialDownloadCommand();
            Command.CommandResult commandResult = command.runGet();
            result = new ExecuteResult(commandResult.OK(), commandResult.getData(), AsyncTaskType.GET_TOKEN);
        } else {
            result = new ExecuteResult(doUpload(), null, AsyncTaskType.UPLOAD);
        }
        return result;
    }

    @Override
    protected void onPostExecute(ExecuteResult result) {
        if (result.getType() == AsyncTaskType.GET_TOKEN) {
            if (result.OK()) {
                ossResult = (ImageCredentialDownloadCommand.OSSResult)result.getData();
                NotifyPrinter.getInstance().notify(NotifyMessage.wrap(null, Consts.NOTIFY_IMAGE_CREDENTIAL_GET));
            }
        } else {
            if (result.OK()) {
                NotifyPrinter.getInstance().notify(NotifyMessage.info(Consts.UPLOAD_IMAGE_OK, Consts.NOTIFY_RECEIVER_DATA_SYNC));
            } else {
                NotifyPrinter.getInstance().notify(NotifyMessage.info(Consts.UPLOAD_IMAGE_FAIL, Consts.NOTIFY_RECEIVER_DATA_SYNC));
            }
        }
    }

    public Uri getOutputMediaFileUri() {
        Uri uri = null;
        File file = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (file != null) {
            uri = Uri.fromFile(file);
        }
        return uri;
    }

    private File getOutputMediaFile(int type){
        // To be safe, you should check that the SDCard is mounted
        // using Environment.getExternalStorageState() before doing this.
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "shchuangzhi.image");
        // This location works best if you want the created images to be shared
        // between applications and persist after your app has been uninstalled.
        if (!mediaStorageDir.exists()){
            if (!mediaStorageDir.mkdirs()){
                XLog.d("failed to create directory");
                return null;
            }
        }

        // Create a media file name
        String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        if (type == MEDIA_TYPE_IMAGE){
            mediaFile = new File(String.format("%s%sIMG_%s_%s_%s.jpg",
                    mediaStorageDir.getPath(),
                    File.separator,
                    bindData.getSchoolNo(),
                    bindData.getNo(),
                    timeStamp));
        }

        return mediaFile;
    }

    private boolean doUpload() {
        boolean uploadOK = false;
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(
                ossResult.getCredentials().getAccessKeyId(),
                ossResult.getCredentials().getAccessKeySecret(),
                ossResult.getCredentials().getSecurityToken());

        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000);
        conf.setSocketTimeout(15 * 1000);
        conf.setMaxConcurrentRequest(5);
        conf.setMaxErrorRetry(2);
        OSSLog.enableLog();
        OSS oss = new OSSClient(context, endpoint, credentialProvider);

        Bitmap p = BitmapFactory.decodeFile(mediaFile.getPath());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        p.compress(Bitmap.CompressFormat.JPEG, 65, baos);
        byte[] image = baos.toByteArray();

        PutObjectRequest put = new PutObjectRequest("quickly56-img-test", "temp/" + mediaFile.getName(), image);
        try {
            PutObjectResult putResult = oss.putObject(put);
            if (putResult.getStatusCode() == HttpStatus.HTTP_OK) {
                String imageUrl = String.format(
                        "http://quickly56-img-test.oss-cn-hangzhou.aliyuncs.com/temp/%s?x-oss-process=image/resize,m_mfit,h_200,w_200", mediaFile.getName());
                ImageUpdateCommand updateCommand = new ImageUpdateCommand(bindData.getNo(), imageUrl);
                Command.CommandResult updateResult = updateCommand.runPost();
                uploadOK = updateResult.OK();
            }
        } catch(ClientException e) {
            XLog.e("", e);
        } catch(ServiceException e) {
            XLog.e("", e);
        } catch(Exception e) {
            XLog.e("", e);
        }

        return uploadOK;
    }

    public enum AsyncTaskType {
        UPLOAD,
        GET_TOKEN
    }

    public class ExecuteResult {
        private boolean ok;
        private Object data;
        private AsyncTaskType type;
        public ExecuteResult(boolean ok, Object data, AsyncTaskType type) {
            this.ok = ok;
            this.type = type;
            this.data = data;
        }

        public boolean OK() {
            return ok;
        }

        public Object getData() {
            return data;
        }

        public AsyncTaskType getType() {
            return type;
        }
    }
}
